using System.Diagnostics;
using System.IO;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;

public partial class SfxProfileEditor : OdinEditorWindow
{
    private const string FX_PREVIEW_SCENE_PATH = "{0}/SfxProfile.unity";
    private bool m_Profiling;
    private SfxProfilerRunner m_Profiler;
    private GameObject m_ProfileEffect;

    private static SfxProfileEditor s_Instance;
    
    [LabelText("测试特效"), OnValueChanged(nameof(ProfileObjectChanged))]
    public GameObject profileSfxScript;
    
    [LabelText("GPU架构"), ValueDropdown(nameof(OnDropdownGPUArchitecture))]
    public string gpuArchitecture = "Mali-T720";
    
    [MenuItem("Tools/资源合规/特效跑分器")]
    private static void OpenWindow()
    {
        if (s_Instance != null)
        {
            s_Instance.Close();
            s_Instance = null;
        }
        s_Instance = GetWindow<SfxProfileEditor>();
        s_Instance.Show();
    }
    
    private ValueDropdownList<string> OnDropdownGPUArchitecture()
    {
        ValueDropdownList<string> v = new ValueDropdownList<string>();
        foreach (string architecture in PerfStandardWithGPU.m_ArchitectureList)
        {
            v.Add(architecture, architecture);
        }
        return v;
    }

    protected override void OnDestroy()
    {
        DispostPlayObject();
        
        if (profileSfxScript && PrefabUtility.IsPartOfPrefabInstance(profileSfxScript.gameObject))
        {
            profileSfxScript.gameObject.SetActive(true);
        }
        EndProfile();
        
        s_Instance = null;
    }

    private void ProfileObjectChanged()
    {
        DispostPlayObject();

        if (profileSfxScript == null)
        {
            playSfxScript = null;
            OnCloneSfx();
            return;
        }
        
        GameObject clone = Instantiate(profileSfxScript.gameObject);
        clone.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy;
        if (PrefabUtility.IsPartOfPrefabInstance(profileSfxScript.gameObject))
        {
            profileSfxScript.gameObject.SetActive(false);
        }
        m_Profiling = false;
        playSfxScript = clone.GetComponent<SfxProfilerScript>();
        if (playSfxScript == null)
        {
            playSfxScript = clone.AddComponent<SfxProfilerScript>();
        }
        Tools.current = Tool.Move;
        Tools.viewTool = ViewTool.None;
        foreach (SceneView view in SceneView.sceneViews)
        {
            view.Focus();
            view.LookAt(playSfxScript.transform.position);
        }
        OnCloneSfx();
    }

    private void DispostPlayObject()
    {
        if (!playSfxScript)
        {
            return;
        }
        if (Application.isPlaying)
        {
            Destroy(playSfxScript.gameObject);
        }
        else
        {
            DestroyImmediate(playSfxScript.gameObject);
        }
    }

    [TitleGroup("性能测试")]
    [HorizontalGroup("性能测试/PerfTest")]
    [PropertySpace, Button("打开性能报告查看器"), DisableIf("@" + nameof(m_Profiling)), PropertyOrder(5.0f)]
    private void OpenReporter()
    {
        string projectPath = Application.dataPath.Replace("Assets", "");
        string fileName = Path.Combine(projectPath, SfxProfiler.REPORTER_REL_PATH, "FXPerformanceDataReporter.exe")
            .Replace("\\", "/");
        ProcessStartInfo startInfo = new ProcessStartInfo()
        {
            FileName = fileName,
            RedirectStandardOutput = false,
            RedirectStandardError = false,
            RedirectStandardInput = false,
            UseShellExecute = false,
            CreateNoWindow = true
        };
        Process process = new Process();
        process.StartInfo = startInfo;
        process.Start();
    }
    
    [HorizontalGroup("性能测试/PerfTest")]
    [InfoBox("正在测试性能，请稍候...", InfoMessageType.None, "@" + nameof(m_Profiling))]
    [PropertySpace, Button("测试性能"), DisableIf("@" + nameof(m_Profiling)), PropertyOrder(5.0f)]
    private void StartProfile()
    {
        if (!profileSfxScript)
        {
            EditorUtility.DisplayDialog("错误", "【测试特效】不能为空", "确定");
            return;
        }
        //已经在播放状态，使其重新开始
        if (EditorApplication.isPlaying)
        {
            EditorUtility.DisplayDialog("错误", "请先退出播放模式" ,"确定");
            return;
        }
        
        m_Profiling = true;

        if (playSfxScript)
        {
            DestroyImmediate(playSfxScript.gameObject);
        }
        
        // 打开预览场景
        EditorSceneManager.OpenScene(string.Format(FX_PREVIEW_SCENE_PATH, SfxProfiler.EditorResourcesPath));

        m_ProfileEffect = Instantiate(profileSfxScript.gameObject);
        m_ProfileEffect.name = profileSfxScript.gameObject.name;
        m_ProfileEffect.SetActive(false);

        GameObject profilerObj = GameObject.Find("ProfilerObj");
        m_Profiler = profilerObj.GetComponent<SfxProfilerRunner>();
        
        m_Profiler.m_ProfileInputs.Clear();
        m_Profiler.m_ProfileInputs.Add(new SfxProfilerRunner.ProfileInput()
        {
            m_Prefab = m_ProfileEffect,
            m_GPUArchitecture = gpuArchitecture
        });
        
        m_Profiler.m_AwakeCallbackInfos.Clear();
        m_Profiler.m_AwakeCallbackInfos.Add(new SfxProfilerRunner.AwakeCallbackInfo()
        {
            m_AssemblyName = "Assembly-CSharp-Editor",
            m_ClassName = "SfxProfileEditor",
            m_FunctionName = nameof(OnProfileAwake),
            m_IsPublic = false
        });
        
        EditorApplication.isPlaying = true;
        //OnEnterPlayMode();
    }
    
    private static void OnProfileAwake()
    {
        if (s_Instance == null)
        {
            s_Instance = GetWindow<SfxProfileEditor>();
        }
        GameObject profilerObj = GameObject.Find("ProfilerObj");
        s_Instance.m_Profiler = profilerObj.GetComponent<SfxProfilerRunner>();
        s_Instance.m_Profiler.m_OnEndProfile = s_Instance.OnEndProfile;
    }

    private void WaiteUtilIsNotPlaying()
    {
        if (Application.isPlaying)
        {
            return;
        }
        EditorApplication.update -= WaiteUtilIsNotPlaying;
        
        m_Profiler = null;

        if (Application.isPlaying)
        {
            Destroy(m_ProfileEffect);
        }
        else
        {
            DestroyImmediate(m_ProfileEffect);
        }
        m_ProfileEffect = null;
        
        GameObject clone = Instantiate(profileSfxScript.gameObject);
        clone.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy;

        m_Profiling = false;
        profileSfxScript = null;
        // s_Instance = GetWindow<NodeControllerPreviewEditor>();
        // m_Profiling = false;
        // m_NodeController = clone.GetComponent<NodeController>();
        // OnOpenWindow();
    }

    private void OnEndProfile()
    {
        if (profileSfxScript)
        {
            profileSfxScript.gameObject.SetActive(true);
        }
        Selection.activeGameObject = profileSfxScript.gameObject;
        EditorApplication.update += WaiteUtilIsNotPlaying;
    }
    
    private void EndProfile()
    {
        if (m_Profiler != null && m_Profiler.m_Profiler is SfxProfiler profiler)
        {
            profiler.ForceEndProfile();
        }
    }
}